package robocup.component.tactics;

import java.util.Arrays;

import robocup.component.ControllerNumbers;
import robocup.component.Prophet;
import robocup.component.WorldModel;
import robocup.component.geometry.Vektor;
import robocup.component.worldobjects.Player;

public class InterceptOpponentState
    extends AbstractState {

  private Player fastestOpponent;

  private Player self;

  /**
   * Constructor
   * 
   * Welche playmodes m�ssen unterst�tzt werden? - play on -
   * 
   * @param parent
   */
  public InterceptOpponentState(
      final StateEvaluation parent) {

    super(parent);
    this.state = STATES.INTERCEPT_OPPONENT;
  }

  @Override
  protected double successProbability() {

    return 0.55;
  }

  @Override
  protected double successBenefit() {

    this.self = this.getWorld().getSelfRef();
    this.fastestOpponent = this.getWorld().getFastestOpponentToBall();
    if (this.fastestOpponent.isGoalie()) {
      return 0;
    }

    if (true) {
      return 1;
      // falsch!!! (rw) geht nur mit Ball!!
      // interceptPosition = wm.getInterceptionPoint(fastestOpponent, self);
    }

    // get the fastest teammate ignoring the defenders
    int cycles = Integer.MAX_VALUE;
    int cyclestmp = Integer.MAX_VALUE;
    final Player[] teammates = this.getWorld().getTeammates();
    Player fastestTeammate = null;
    for (int i = 0; i < teammates.length; i++) {
      if (teammates[i] != null && !this.isDefender(this.getWorld(),
          teammates[i])) {
        // rw deprecated!! use playerMovements as in ballinterception!!
        cyclestmp = 0;// wm.predictCyclesToReachPosition(teammates[i],
        // interceptPosition);
        if (cyclestmp < cycles) {
          cycles = cyclestmp;
          fastestTeammate = teammates[i];
        }
      }
    }

    // if(fastestTeammate != null)System.out.println("fastest: " +
    // fastestTeammate.getNumber() + " in Cycle: " + wm.getCycle());

    if (fastestTeammate != null && fastestTeammate.isMe()) {
      if (this.isBehindOpponent(this.fastestOpponent.getPosition())) {
        return 1;
      }
      return 0;
    }
    else {
      return 0;
    }

  }

  /**
   * Returns true if the fastest player to ball is an opponent and this player
   * is not a defender
   */
  @Override
  public boolean preCondition() {

    if (true) {
      return false;
    }

    // 1. check the PlayMode
    if (!this.checkPlayMode()) {
      return false;
    }

    // no ball, no fun
    if (!this.getWorld().getBallRef().isReliable()) {
      return false;
    }

    // 2. ball not interceptable directly
    final Prophet prophet = this.getProphet();
    if (prophet.iAmFastestToBall()) {
      return false;
    }

    if (prophet.inPossessionOfBall() != ControllerNumbers.TEAM.OPPONENT) {
      return false;
    }

    // 3. among the list of players to intercept the
    // opponent (only teammates considered)
    return false; // (prophet.iAmFastestToOpponent());
  }

  /**
   * Returns true if the Player is behind the Opponent relative to the ball
   * 
   * @param wm
   * @param oppPos
   * @return
   */
  private boolean isBehindOpponent(final Vektor oppPos) {

    final Vektor ownPos = this.self.getPosition();
    final Vektor ballPos = this.getWorld().getBallRef().getPosition();

    final Vektor oppToBall = ballPos.sub(oppPos);
    final Vektor oppToMe = ownPos.sub(oppPos);

    final double oppAngle = oppToBall.getAngleBetween(oppToMe);
    final double angle = Vektor.normalize(oppAngle);

    // if behind opponent
    // if(angle > 90 || angle < -90)

    // if in front of opponent
    if (angle < 90 && angle > -90) {
      return false;
    }
    else {
      return true;
    }

  }

  /**
   * Returns true if the given Player is a defender
   * 
   * @param wm - the current worldmodel
   * @param p - the player to check
   * @return
   */
  private boolean isDefender(final WorldModel wm,
      final Player p) {

    if (Player.ROLE.META_POSITION_DEFENSE.contains(p.getDefaultRole())) {
      return true;
    }
    else {
      return false;
    }
  }

  @Override
  public void calculateMainAction() {

    // Prophet prophet = this.getProphet();
    // Vektor ip = prophet.getNextOppInterceptionPoint();
    // if (getWorld().getSelfRef().getDistance(ip) < 1) {
    // closeOpponentIntercept();
    // } else {
    // if (getWorld().getDistance(ip) < 15)
    // mainAction = BasicActionFactory.moveToPos(getWorld(), ip,
    // ControllerNumbers.STAMINA_LEVEL.LOW);
    // else
    // mainAction = BasicActionFactory.moveToPos(getWorld(), ip,
    // ControllerNumbers.STAMINA_LEVEL.HIGH);
    // }
    //		
    // System.out.println(getWorld() + " EXECUTED INTERCEPT OPPONENT:
    // ************ ");
  }

  /**
   * always watch opponent or ball
   */
  @Override
  public void calculateTurnNeckAction() {

    if (this.fastestOpponent == null) {
      super.calculateTurnNeckAction();
      return;
    }

    final double[] weights = new double[23];
    Arrays.fill(weights, 0);

    weights[22] = 1;
    weights[this.fastestOpponent.getNumber() - 1 + 11] = 1;

    this.turnNeckAction = getProphet().getTurnNeckAction(this.state, this.mainAction, this.viewModeAction, weights);
  }

}
